#include "types.h"
#include "defs.h"
#include "param.h"
#include "mmu.h"
#include "proc.h"
#include "fs.h"
#include "spinlock.h"
#include "sleeplock.h"
#include "file.h"


struct  {
  struct spinlock lock;
  char data[1024];
  uint nread;     // number of bytes read
  uint nwrite;    // number of bytes written  
} devcache;

void osdevinit(){
  initlock(&devcache.lock,"osdevlock");
  devcache.nread=devcache.nwrite=0;
}


//PAGEBREAK: 40
int
osdevwrite(char *addr, int n)
{
  int i;

  acquire(&devcache.lock);
  for(i = 0; i < n; i++){
    while(devcache.nwrite == devcache.nread + 1024){  //DOC: pipewrite-full
      if(myproc()->killed){
        release(&devcache.lock);
        return -1;
      }
      wakeup(&devcache.nread);      
    }
    devcache.data[devcache.nwrite++ % 1024] = addr[i];
  }
  wakeup(&devcache.nread);  //DOC: pipewrite-wakeup1
  release(&devcache.lock);
  //cprintf("write to kernel: %s\n",devcache.data);
  return n;
}

int
osdevread(char *addr, int n)
{
  int i;

  acquire(&devcache.lock);
  while(devcache.nread == devcache.nwrite){  //DOC: pipe-empty
    if(myproc()->killed){
      release(&devcache.lock);
      return -1;
    }
    sleep(&devcache.nread, &devcache.lock); //DOC: piperead-sleep
  }
  for(i = 0; i < n; i++){  //DOC: copy
    if(devcache.nread == devcache.nwrite)
      break;
    addr[i] = devcache.data[devcache.nread++ % 1024];
  }  
  release(&devcache.lock);
  return i;
}
